#pragma once
#include <iostream>
#include <functional>
class EpollServer;

namespace NS_Connection
{
    class Connection;
    using io_handler_t = std::function<void(Connection *)>;

    class Connection
    {
    public:
        Connection(int fd, uint32_t event, EpollServer* R) : _fd(fd), _event(event), _R(R) {}

        void RegisterIOHandler(io_handler_t reader, io_handler_t writer, io_handler_t exceptor)
        {
            _reader = reader;
            _writer = writer;
            _exceptor = exceptor;
        }

        int GetSockFd()
        {
            return _fd;
        }

        uint32_t GetEvent()
        {
            return _event;
        }

        void SetEvent(uint32_t event)
        {
            _event = event;
        }

        bool OutEmpty()
        {
            return _outbuffer.empty();
        }

        void Close()
        {
            if(_fd > 0)
            {
                close(_fd);
            }
        }

        ~Connection() {}

    private:
        int _fd;
        uint32_t _event;

    public:
        io_handler_t _reader;
        io_handler_t _writer;
        io_handler_t _exceptor;

        std::string _inbuffer;
        std::string _outbuffer;

        EpollServer* _R;
    };

    class Factory
    {
    public:
        static Connection *BuildListenConn(int fd, uint32_t event, EpollServer* R, io_handler_t reader)
        {
            Connection *conn = new Connection(fd, event, R);
            conn->RegisterIOHandler(reader, nullptr, nullptr);

            return conn;
        }

        static Connection *BuildNormalConn(int fd, uint32_t event, EpollServer* R, io_handler_t reader, io_handler_t writer, io_handler_t exceptor)
        {
            Connection *conn = new Connection(fd, event, R);
            conn->RegisterIOHandler(reader, writer, exceptor);

            return conn;
        }
    };
}